package util;

import data.DataHelper;
import jxl.read.biff.BiffException;
import obj.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class CheckLinks {
    public static List<String> checkedModels;

    public static void main(String[] args) throws IOException, InterruptedException, BiffException {
        checkEquiv();
//        checkAccums("Nokia");
//        checkAccums("Samsung");
//        checkAccums("Sony Ericsson");
//        checkAccums("Motorola");
//        checkAccums("HTC");
//        checkAccums("Blackberry");
//        checkChargers("Nokia");
//        checkChargers("Samsung");
//        checkChargers("Sony Ericsson");
//        checkChargers("Blackberry");
//        checkBodies("Nokia");
//        checkBodies("Samsung");
//        checkBodies("Sony Ericsson");
//        checkRepairs("Sony Ericsson");
//        checkRepairs("Nokia");
//        checkRepairs("Samsung");
//        checkRepairs("HTC");
//        checkRepairs("BlackBerry");
//        checkRepairs("iPhone");
    }

    private static void checkEquiv() throws IOException, InterruptedException {
//        List<Accum> accums = Accum.parseAccums();
        List<String> failedLinks = new ArrayList<String>();
        Map<String, List<String>> modelsPerBrand = Accum.parseModels();
        for (String brandName : modelsPerBrand.keySet()) {
            if (
                    brandName.equalsIgnoreCase("apple") ||
                    brandName.equalsIgnoreCase("nokia") ||
                    brandName.equalsIgnoreCase("samsung") ||
//                    brandName.equalsIgnoreCase("sony ericsson") ||
                    brandName.equalsIgnoreCase("blackberry") ||
                    brandName.equalsIgnoreCase("lg") ||
                    brandName.equalsIgnoreCase("motorola") ||
                    brandName.equalsIgnoreCase("craftmann") ||
                    brandName.equalsIgnoreCase("nokiamaxcell")) {
                continue;
            }
            List<String> processedModels = new ArrayList<String>();
            PrintStream out = new PrintStream(new FileOutputStream("data/failed/" + brandName + "failed.txt"));
            for (String model : modelsPerBrand.get(brandName)) {
                if (processedModels.contains(model)) {
                    continue;
                }
                String chargerUrl = Charger.ORIG_URL_NETWORK + DataHelper.codeInURL(brandName + "_" + model).toLowerCase();
                String autoChargerUrl = Charger.ORIG_URL_AUTO + DataHelper.codeInURL(brandName + "_" + model).toLowerCase();
                String bodyUrl = Body.BASE_URL + DataHelper.codeInURL(brandName + "_" + model).toLowerCase();
                String headsetUrl = Headset.BASE_URL + DataHelper.codeInURL(brandName + "_" + model).toLowerCase();
                String repairUrl = Templ.BASE_URL + DataHelper.codeInURL("remont_" + brandName + "_" + model).toLowerCase();
                if (!checkNotFail(chargerUrl, model)) {
                    failedLinks.add(chargerUrl);
                    out.println(model + ", " + chargerUrl);
                }
                if (!checkNotFail(autoChargerUrl, model)) {
                    failedLinks.add(autoChargerUrl);
                    out.println(model + ", " + autoChargerUrl);
                }
//                if (!checkNotFail(bodyUrl, model)) {
//                    failedLinks.add(bodyUrl);
//                    out.println(bodyUrl);
//                }
//                if (!checkNotFail(repairUrl, model)) {
//                    failedLinks.add(repairUrl);
//                    out.println(repairUrl);
//                }
//                if (!checkNotFail(headsetUrl, model)) {
//                    failedLinks.add(headsetUrl);
//                    out.println(headsetUrl);
//                }
                processedModels.add(model);
            }
            System.out.println("-----------------------------------------" + brandName);
            out.close();
        }
    }

    private static void checkRepairs(String brand) throws BiffException, IOException, InterruptedException {
        checkedModels = new ArrayList<String>();
        List<Templ> repairs = Templ.parseTempls("phones", "remont", 100);
        for (Templ repair : repairs) {
            if (repair.vendor.equalsIgnoreCase(brand)) {
                check(repair.models.toArray(new String[]{}), repair.modelUrls);
            }
        }
        System.out.println("Done remont " + brand);
    }

    private static void checkBodies(String brand) throws IOException, InterruptedException {
        List<Body> bodies = Body.parseBodies(brand, 1);
        for (Body body : bodies) {
            check(body.url, body.model);
        }
        System.out.println("Done bodies " + brand);
    }

    private static void checkChargers(String brand) throws IOException, InterruptedException {
        checkedModels = new ArrayList<String>();
        List<Charger> chargers = Charger.parseChargers(brand, 1);
        boolean auto = chargers.get(0).auto;
        for (Charger charger : chargers) {
            if (charger.auto != auto) {
                checkedModels = new ArrayList<String>();
                auto = charger.auto;
            }
            check(charger.url, charger.name);
            check(charger.models, charger.modelURLs);
        }
        System.out.println("Done chargers " + brand);
    }

    private static void checkAccums(String brand) throws InterruptedException, IOException {
        checkedModels = new ArrayList<String>();
        List<Accum> accums = Accum.parseAccums(brand, 1);
        for (Accum accum : accums) {
            check(accum.url, accum.name);
            check(accum.devices, accum.deviceURLs);
        }
        System.out.println("Done accums " + brand);
    }

    public static void check(String[] models, List<String> urls) throws InterruptedException, IOException {
        int i = 0;
        for (String model : models) {
            String url = urls.get(i++);
            if (checkedModels.contains(model)) {
                System.out.println("Already checked: " + model);
                continue;
            }
            check(url, model);
            checkedModels.add(model);
        }
    }

    public static void check(String url, String name) throws InterruptedException, IOException {
        if (!urlExists(url, name)) {
            throw new IllegalStateException("URL not exists: " + url);
        }
        Thread.sleep(300);
    }

    public static boolean checkNotFail(String url, String name) throws InterruptedException, IOException {
        if (!urlExists(url, name)) {
            return false;
        }
        Thread.sleep(300);
        return true;
    }

    public static boolean urlExists(String url, String name) throws IOException, InterruptedException {
//        Document doc = null;
//        while (true) {
        Document doc;
        try {
            doc = Jsoup.connect(url).timeout(10000).get();
//                break;
        } catch (Exception e) {
            return false;
//                System.out.println("Timeout: " + url);
//                Thread.sleep(300);
        }
//        }
        String h1 = doc.getElementsByTag("h1").text();
        System.out.println(url);
        return h1.toLowerCase().contains(name.trim().toLowerCase());
    }
}
